package com.sy.olddriver.service.impl;

import com.sy.olddriver.constant.AppConstant;
import com.sy.olddriver.dao.ProductDao;
import com.sy.olddriver.dao.impl.ProductDaoImpl;
import com.sy.olddriver.dto.CartItem;
import com.sy.olddriver.dto.Result;
import com.sy.olddriver.entity.Product;
import com.sy.olddriver.entity.User;
import com.sy.olddriver.exception.OldDriverException;
import com.sy.olddriver.service.CartService;
import com.sy.olddriver.utils.HttpUtils;
import com.sy.olddriver.utils.RandomUtils;
import com.sy.olddriver.utils.RedisUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * CartService接口的实现类
 *
 * @author Administrator
 */
public class CartServiceImpl implements CartService {
    private ProductDao productDao = new ProductDaoImpl();

    @Override
    public Result addToCart(String pid, String count) {
        Result result = new Result();
        try {

            //校验添加的数量是否是一个整数
            if (!count.matches(AppConstant.INTEGER_REGEX)) {
                throw new OldDriverException("添加购物车的数量必须是一个整数");
            }
            //获取当前登录的用户信息
            User loginUser = HttpUtils.getLoginUser();
            String redisCartKey;
            //(1)如果用户未登录，则将购物车信息保存为临时购物车信息
            if (null == loginUser) {
                //获取Cookie中有无用来表示当前客户端离线购物车状态的凭证
                String tempCartCookie = HttpUtils.getCookie(AppConstant.TEMP_CART_COOKIE_NAME);
                //a.如果有，则在Redis对应的临时的购物车信息中，添加这一次的购物车数据
                if (StringUtils.isNotBlank(tempCartCookie)) {
                    //获取当前Cookie中的临时购物车凭证在Redis中对应的数据
                    redisCartKey = AppConstant.TEMP_CART_REDIS_PREFIX + tempCartCookie;
                }
                //b.如果没有，则在Cookie中首先创建这个凭证，然后在Redis中添加当前客户端的第一条购物车数据
                else {
                    //在Cookie中创建一个用于表示当前客户端对应购物车的凭证
                    String tempCartCookieId = RandomUtils.getRandomStr();
                    HttpUtils.setCookie(AppConstant.TEMP_CART_COOKIE_NAME, tempCartCookieId, null);
                    redisCartKey = AppConstant.TEMP_CART_REDIS_PREFIX + tempCartCookieId;
                }
                //在Redis中添加本次的购物车数据
            }
            //(2)如果用户已经登录，则将购物车信息保存为和具体用户编号相关的购物车信息
            else {
                redisCartKey = AppConstant.USER_CART_REDIS_PREFIX + loginUser.getId();
                //获取Redis中当前用户编号对应的购物车信息
                //a.如果不存在购物车信息，在Redis中创建当前用户对应的购物车信息并添加第一条购物车记录
                //b.如果存在购物车信息，在Redis当前用户对应的购物车中添加本次的购物车记录
            }
            RedisUtils.hincrBy(redisCartKey, pid, Long.parseLong(count));
        } catch (Exception e) {
            e.printStackTrace();
            result.setSuccess(false);
            result.setErrMsg(e.getMessage());
        }
        return result;

    }

    @Override
    public void mergeCart(Integer userId) {
        //1.获取当前离线状态下的购物车信息
        String tempCartKey = AppConstant.TEMP_CART_REDIS_PREFIX + HttpUtils.getCookie(AppConstant.TEMP_CART_COOKIE_NAME);
        Map<String, String> tempCartItems = RedisUtils.hgetAll(tempCartKey);

        //2.获取当前登录用户的购物车信息
        String userCartKey = AppConstant.USER_CART_REDIS_PREFIX + userId;

        //3.将离线状态的购物车和具体用户的购物车合并
        //合并过程中如果出现产品编号相同的情况，则对其数量进行合并
        if (MapUtils.isNotEmpty(tempCartItems)) {
            for (Map.Entry<String, String> tempCartItem : tempCartItems.entrySet()) {
                String pid = tempCartItem.getKey();
                String count = tempCartItem.getValue();
                RedisUtils.hincrBy(userCartKey, pid, Long.parseLong(count));
            }
        }

        //4.删除临时状态下的购物车数据
        RedisUtils.del(tempCartKey);

    }

    @Override
    public Result getCartItems() {
        Result result = new Result();
        try {
            String key = getRedisCartKey();
            //从Redis中获取购物车信息
            Map<String, String> redisCartItems = RedisUtils.hgetAll(key);
            //封装最后返回给前端的购物车的信息
            List<CartItem> cartItemList = new ArrayList<>();
            if (MapUtils.isNotEmpty(redisCartItems)) {
                for (Map.Entry<String, String> redisCartItem : redisCartItems.entrySet()) {
                    CartItem cartItem = new CartItem();
                    cartItem.setProduct(productDao.getProductById(redisCartItem.getKey()));
                    cartItem.setCount(Integer.parseInt(redisCartItem.getValue()));
                    cartItemList.add(cartItem);
                }
            }
            result.setData(cartItemList);
        } catch (Exception e) {
            e.printStackTrace();
            result.setSuccess(false);
            result.setErrMsg(e.getMessage());
        }
        return result;
    }

    @Override
    public Result clearCart() {
        Result result = new Result();
        try {
            //获取Reids中购物车的key
            String key = getRedisCartKey();

            //删除Redis中购物车key对应的数据
            if (!RedisUtils.del(key)) {
                throw new OldDriverException("购物车信息可能已经被删除了！");
            }

            //将此时的购物车信息进行返回
            result.setData(getCartItems().getData());
        } catch (Exception e) {
            e.printStackTrace();
            result.setSuccess(false);
            result.setErrMsg(e.getMessage());
        }
        return result;
    }

    @Override
    public Result delOneCartItem(String pid) {
        Result result = new Result();
        try {
            //获取Reids中购物车的key
            String key = getRedisCartKey();
            //删除Redis中购物车key对应的数据
            if (!RedisUtils.hdel(key, pid)) {
                throw new OldDriverException("当前购物车商品信息可能已经被删除");
            }
            //将此时的购物车信息进行返回
            result.setData(getCartItems().getData());
        } catch (Exception e) {
            e.printStackTrace();
            result.setSuccess(false);
            result.setErrMsg(e.getMessage());
        }
        return result;
    }

    @Override
    public Result updateCartItem(String pid, String count) {
        Result result = new Result();
        try {
            //获取Reids中购物车的key
            String key = getRedisCartKey();
            //更新Redis中购物车商品的数量
            RedisUtils.hset(key, pid, count);
            //将此时的购物车信息进行返回
            result.setData(getCartItems().getData());
        } catch (Exception e) {
            e.printStackTrace();
            result.setSuccess(false);
            result.setErrMsg(e.getMessage());
        }
        return result;
    }


    /**
     * 用于获取Redis在购物车中的key（分为离线和登录的情况）
     *
     * @return 购物车在Redis中对应的key值
     */
    private String getRedisCartKey() {
        //获取当前的登录用户
        User loginUser = HttpUtils.getLoginUser();
        String key;
        //1.如果用户已经登录，则获取当前登录用户的购物车信息
        if (null != loginUser) {
            key = AppConstant.USER_CART_REDIS_PREFIX + loginUser.getId();
        }
        //2.如果用户未登录，则获取当前客户端的临时购物车信息
        else {
            key = AppConstant.TEMP_CART_REDIS_PREFIX + HttpUtils.getCookie(AppConstant.TEMP_CART_COOKIE_NAME);
        }
        return key;
    }

}
